package de.herberlin.sudoku;

import java.io.Serializable;
import java.util.BitSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

/**
 * Class representing a counting unit
 *
 * @author herberlin
 * @created 30.05.2006
 */
public class Group implements Serializable {

	static final long serialVersionUID = 1L;

	public static final int TYPE_ROW = 2;

	public static final int TYPE_COLUMN = 1;

	public static final int TYPE_SQUARE = 3;

	private int type = Constants.INT_NOT_SET;

	private List fields = new LinkedList();

	public Group() {
		super();
	}

	public Group(int type) {
		this.type = type;
	}

	public int getType() {
		return type;
	}

	public void setType(int type) {
		this.type = type;
	}

	public void add(Field field) {
		fields.add(field);
	}

	/**
	 * Finds the field that leads to a confilict with updated field
	 *
	 * @param updated
	 * @return the first conflict field or null if no conflict rised by the
	 *         update
	 */
	public Field getConflictField(Field updated) {

		assert updated != null;

		if (fields.contains(updated)) {

			Iterator it = fields.iterator();
			while (it.hasNext()) {
				Field current = (Field) it.next();
				if (!current.equals(updated)
						&& current.getValue() == updated.getValue()) {
					return current;
				}
			}
		}
		return null;
	}

	public boolean isResolved() {

		BitSet bitSet = new BitSet(fields.size());
		Iterator it = fields.iterator();
		while (it.hasNext()) {
			Field field = (Field) it.next();
			if (field.getValue() == Constants.INT_NOT_SET) {
				// a field is not set;
				return false;
			} else if (bitSet.get(field.getValue())) {
				// field already existing with this value
				return false;
			} else {
				// set the field
				bitSet.set(field.getValue());
			}
		}

		// number of bits set to true must match the number of fields
		// should always be true, otherwise we've already returned above
		assert (bitSet.cardinality() == fields.size());
		return true;
	}

	public String toString() {
		return "type=" + type + ", Fields=" + fields;
	}

	public Field[] getFields() {
		return (Field[]) fields.toArray(new Field[fields.size()]);
	}
}
